package core

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"math/rand"
	"net"
	"time"
)

func GetMilliID() uint64 {
	return uint64(time.Now().UnixMilli())
}

// B（字节）
// KB（千字节，1KB = 1024B）
// MB（兆字节，1MB = 1024KB）
// GB（吉字节，1GB = 1024MB）
// TB（太字节，1TB = 1024GB）
// PB（拍字节，1PB = 1024TB）
// EB（艾字节，1EB = 1024PB）
// ZB（泽字节，1ZB = 1024EB）
// YB（尧字节，1YB = 1024ZB）
func GetValue(bytes uint64) string {
	const (
		_  = iota
		KB = 1 << (10 * iota) // 1024
		MB
		GB
		TB
		PB
		EB
	)
	switch {
	case bytes >= EB:
		return fmt.Sprintf("%.2f PB", float64(bytes)/EB)
	case bytes >= PB:
		return fmt.Sprintf("%.2f PB", float64(bytes)/PB)
	case bytes >= TB:
		return fmt.Sprintf("%.2f TB", float64(bytes)/TB)
	case bytes >= GB:
		return fmt.Sprintf("%.2f GB", float64(bytes)/GB)
	case bytes >= MB:
		return fmt.Sprintf("%.2f MB", float64(bytes)/MB)
	case bytes >= KB:
		return fmt.Sprintf("%.2f KB", float64(bytes)/KB)
	default:
		return fmt.Sprintf("%d B", bytes)
	}
}

func TcpSendBytes(conn net.Conn, data []byte) error {
	if conn == nil {
		return nil
	}
	buf := data
	for len(buf) > 0 {
		n := 0
		var err error
		//如果是大包，则分包发送
		if len(buf) > 1460 {
			n, err = conn.Write(buf[0:1460])
		} else {
			n, err = conn.Write(buf)
		}

		if err != nil {
			return err
		}
		buf = buf[n:]
	}
	return nil
}

// read 2byte data
func ReadUint16(conn net.Conn) (uint16, error) {
	data, err := readBytes(conn, 2)
	if err != nil {
		return 0, err
	}
	return binary.BigEndian.Uint16(data), nil
}
func WriteUint16(buf *bytes.Buffer, value uint16) ([]byte, error) {
	//buf := bytes.NewBuffer(nil)
	if err := binary.Write(buf, binary.BigEndian, value); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
func ReadUint16FromBytes(data []byte) (uint16, error) {
	if len(data) < 2 {
		return 0, fmt.Errorf("data too short to read uint16")
	}
	return binary.BigEndian.Uint16(data[:2]), nil
}

// read 4byte data
func ReadUint32(conn net.Conn) (uint32, error) {
	data, err := readBytes(conn, 4)
	if err != nil {
		return 0, err
	}
	return binary.BigEndian.Uint32(data), nil
}
func ReadUint32FromBytes(data []byte) (uint32, error) {
	if len(data) < 4 {
		return 0, fmt.Errorf("data too short to read uint32")
	}
	return binary.BigEndian.Uint32(data[:4]), nil
}
func WriteUint32(buf *bytes.Buffer, value uint32) ([]byte, error) {
	//buf := bytes.NewBuffer(nil)
	if err := binary.Write(buf, binary.BigEndian, value); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

// 4byte length + data
func ReadString(conn net.Conn) (string, error) {
	length, err := ReadUint32(conn)
	if err != nil {
		return "", err
	}
	data, err := readBytes(conn, length)
	if err != nil {
		return "", err
	}
	return string(data), nil
}
func ReadStringFromBytes(data []byte) (string, error) {
	if len(data) < 4 {
		return "", fmt.Errorf("data too short to read string")
	}
	length := binary.BigEndian.Uint32(data[:4])
	if len(data) < int(4+length) {
		return "", fmt.Errorf("data too short to read string of length %d", length)
	}
	return string(data[4 : 4+length]), nil
}
func ReadUint64(conn net.Conn) (uint64, error) {
	data, err := readBytes(conn, 8)
	if err != nil {
		return 0, err
	}
	return binary.BigEndian.Uint64(data), nil
}
func ReadUint64FromBytes(data []byte) (uint64, error) {
	if len(data) < 8 {
		return 0, fmt.Errorf("data too short to read uint64")
	}
	return binary.BigEndian.Uint64(data[:8]), nil
}
func WriteUint64(buf *bytes.Buffer, value uint64) ([]byte, error) {
	//buf := bytes.NewBuffer(nil)
	if err := binary.Write(buf, binary.BigEndian, value); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

// 4byte length + data
func WriteString(buf *bytes.Buffer, str string) ([]byte, error) {
	//buf := bytes.NewBuffer(nil)
	//data := []byte(str)
	if err := binary.Write(buf, binary.BigEndian, uint32(len(str))); err != nil {
		return nil, err
	}
	if _, err := buf.WriteString(str); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
func ReadByte(conn net.Conn) (byte, error) {
	data, err := readBytes(conn, 1)
	if err != nil {
		return 0, err
	}
	return data[0], nil
}

// read n bytes from conn
func readBytes(conn net.Conn, length uint32) ([]byte, error) {
	var data bytes.Buffer
	slen := length
	count := 0
	for {
		buf := make([]byte, slen)
		n, err := conn.Read(buf)
		if err != nil {
			return data.Bytes(), err
		}
		count += n
		data.Write(buf[:n])
		if uint32(count) >= length {
			break
		}
		slen -= uint32(n)
	}
	return data.Bytes(), nil
}

// 4byte length + data
func ReadBytes(conn net.Conn) ([]byte, error) {
	length, err := ReadUint32(conn)
	if err != nil {
		return nil, err
	}
	data, err := readBytes(conn, length)
	if err != nil {
		return nil, err
	}
	return data, nil
}

// 4byte length + []byte
func ReadBytesFromBytes(data []byte) ([]byte, error) {
	if len(data) < 4 {
		return nil, fmt.Errorf("data too short to read string")
	}
	length := binary.BigEndian.Uint32(data[:4])
	if len(data) < int(4+length) {
		return nil, fmt.Errorf("data too short to read string of length %d", length)
	}
	return data[4 : 4+length], nil
}

// 4byte length + data
func WriteBytes(buffer *bytes.Buffer, data []byte) ([]byte, error) {
	//buffer := bytes.NewBuffer(nil)
	if err := binary.Write(buffer, binary.BigEndian, uint32(len(data))); err != nil {
		return nil, err
	}
	if _, err := buffer.Write(data); err != nil {
		return nil, err
	}
	return buffer.Bytes(), nil
}

func GetRand(min, max int) int {
	if min >= max {
		return min
	}
	// 生成 [0, max-min] 的随机数，再加上 min 偏移
	return min + rand.Intn(max-min+1)
}
